package nachos.userprog;

import nachos.machine.*;
import nachos.threads.*;
import nachos.userprog.*;

/**
 * UThread 是一个 KThread，除了 Nachos 内核代码外，它还可以在用户进程内执行用户程序代码
 */
public class UThread extends KThread {
    /**
     * 分配一个新的 UThread
     */
    public UThread(UserProcess process) {
        super();

        setTarget(new Runnable() {
            public void run() {
                // 让处理器开始运行
                runProgram();
            }
        });

        this.process = process;
    }

    private void runProgram() {
        // 初始化处理器的寄存器值
        process.initRegisters();
        process.restoreState();

        // 让处理器开始运行，从而不断取指令，执行指令
        Machine.processor().run();

        Lib.assertNotReached();
    }

    /**
     * 在将处理器交给另一个线程之前保存状态
     */
    protected void saveState() {
        process.saveState();

        for (int i = 0; i < Processor.numUserRegisters; i++)
            userRegisters[i] = Machine.processor().readRegister(i);

        super.saveState();
    }

    /**
     * 在再次接收处理器之前恢复状态
     */
    protected void restoreState() {
        super.restoreState();

        for (int i = 0; i < Processor.numUserRegisters; i++)
            Machine.processor().writeRegister(i, userRegisters[i]);

        process.restoreState();
    }

    /**
     * 用户寄存器集的存储
     * <p>
     * 能够运行用户代码的线程实际上有两组 CPU 寄存器：
     * 一个用于在执行用户代码时的状态，另一个用于在执行内核代码时的状态
     * 当此线程未运行时，其用户状态存储在此处
     */
    public int userRegisters[] = new int[Processor.numUserRegisters];

    /**
     * 此线程所属的进程
     */
    public UserProcess process;
}
